package handler

import (
	"code.byted.org/mobaijie/sender/define"
	"context"
	"fmt"
	"github.com/sirupsen/logrus"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

var log = logrus.New()

// 将邮件各个部分分别发送
func SendDifferentPartToSmtpServer(ctx context.Context) error {
	startTime := time.Now().Unix()
	// 解析数据
	err, parseData := ParseEmail(ctx, define.InputEmlFilePath)
	if err != nil {
		log.Errorf("parse data fail, err: %s", err.Error())
		return err
	}
	var sonErr atomic.Value
	var waitGroup sync.WaitGroup
	waitGroup.Add(5)
	// 发送全部内容
	go func() {
		log.Infof("start sendAllContent")
		err, resp := sendAllContent(ctx, parseData)
		waitGroup.Done()
		if err != nil {
			sonErr.Store(err)
			log.Errorf("sendAllContent fail, err: %s", err)
		}
		log.Infof("sendAllContent resp: %+v", resp)
	}()

	// 发送正文内容
	go func() {
		log.Infof("start sendPlainText")
		err, resp := sendPlainText(ctx, parseData.PlainText)
		waitGroup.Done()
		if err != nil {
			sonErr.Store(err)
			log.Errorf("sendPlainText fail, err: %s", err)
		}
		log.Infof("sendPlainText resp: %+v", resp)
	}()

	// 发送全部图片
	go func() {
		log.Infof("start sendAllImages")
		err, resp := sendAllImages(ctx, parseData)
		waitGroup.Done()
		if err != nil {
			sonErr.Store(err)
			log.Errorf("sendAllContent fail, err: %s", err)
		}
		log.Infof("sendAllImages resp: %+v", resp)
	}()

	// 发送全部链接
	go func() {
		log.Infof("start sendAllLinks")
		err, resp := sendAllLinks(ctx, parseData.AllContent)
		waitGroup.Done()
		if err != nil {
			sonErr.Store(err)
			log.Errorf("sendAllContent fail, err: %s", err)
		}
		log.Infof("sendAllLinks resp: %+v", resp)
	}()

	// 发送全部附件(包括内嵌图片)
	go func() {
		log.Infof("start sendAllAttachments")
		err, resp := sendAllAttachments(ctx, parseData)
		waitGroup.Done()
		if err != nil {
			sonErr.Store(err)
			log.Errorf("sendAllAttachments fail, err: %s", err)
		}
		log.Infof("sendAllAttachments resp: %+v", resp)
	}()
	waitGroup.Wait()
	val, _ := sonErr.Load().(error)
	endTime := time.Now().Unix()
	log.Infof("time cost: %d", endTime-startTime)
	return val
}

// 发送邮件的全部内容
func sendAllContent(ctx context.Context, parseData *define.EmlParseData) (error, *define.SmtpResp) {
	htmlBody := parseData.AllContent
	// 构造附件字符串
	attachmentList := make([]string, 0)
	attachmentList = append(attachmentList, parseData.ImageAttachments...)
	attachmentList = append(attachmentList, parseData.StreamAttachments...)
	attachmentBody := strings.Join(attachmentList, "\n\n")
	req := define.NewSmtpReq(htmlBody, attachmentBody, define.AllContentTag)
	req.Subject = define.SendAllContent
	err, resp := SendEmail(ctx, req)
	return err, resp
}

// 发送所有图片
func sendAllImages(ctx context.Context, parseData *define.EmlParseData) (error, *define.SmtpResp) {
	htmlBody := parseData.AllContent
	imgList := make([]string, 0)
	log.Infof("htmlBody: %s", htmlBody)
	imgList = append(imgList, "<h1>images</h1><br/>")
	for {
		singleImg := getSingleImg(&htmlBody)
		if singleImg == "" {
			break
		}
		imgList = append(imgList, singleImg)
		log.Infof("singleImg: %s", singleImg)
	}
	log.Infof("imgList: %+v", imgList)
	req := define.NewSmtpReq(strings.Join(imgList, "\n"), strings.Join(parseData.ImageAttachments, "\n\n"), define.ImageTag)
	req.Subject = define.SendOnlyImages
	err, resp := SendEmail(ctx, req)
	return err, resp
}

// 发送所有链接
func sendAllLinks(ctx context.Context, wholeHtmlBody string) (error, *define.SmtpResp) {
	linkList := make([]string, 0)
	linkList = append(linkList, "<h1>links</h1>")
	// 解析出所有a标签
	for {
		singleLinkHref := getSingleLink(&wholeHtmlBody)
		if singleLinkHref == "" {
			break
		}
		if define.MailRegexp.MatchString(singleLinkHref) || define.MailToRegexp.MatchString(singleLinkHref) {
			continue
		}
		linkList = append(linkList, fmt.Sprintf("<a href=\"%s\">%s</a><br />", singleLinkHref, singleLinkHref))
		log.Infof("singleLink: %s", fmt.Sprintf("<a href=\"%s\">%s</a><br />", singleLinkHref, singleLinkHref))
	}
	log.Infof("linkList: %+v", linkList)
	req := define.NewSmtpReq(strings.Join(linkList, "\n"), "", define.LinkTag)
	req.Subject = define.SendOnlyLinks
	err, resp := SendEmail(ctx, req)
	return err, resp
}

// 发送正文文字内容
func sendPlainText(ctx context.Context, content string) (error, *define.SmtpResp) {
	req := define.NewSmtpReq(content, "", define.PlainTextTag)
	req.Subject = define.SendOnlyPlainText
	err, resp := SendEmail(ctx, req)
	return err, resp
}

// 发送所有附件
func sendAllAttachments(ctx context.Context, parseData *define.EmlParseData) (error, *define.SmtpResp) {
	htmlBody := "<h1>attachments</h1>"
	// 构造附件字符串
	attachmentList := make([]string, 0)
	if len(parseData.ImageAttachments) != 0 {
		attachmentList = append(attachmentList, parseData.ImageAttachments...)
	}
	if len(parseData.StreamAttachments) != 0 {
		attachmentList = append(attachmentList, parseData.StreamAttachments...)
	}
	attachmentBody := strings.Join(attachmentList, "\n\n")
	req := define.NewSmtpReq(htmlBody, attachmentBody, define.AttachmentTag)
	req.Subject = define.SendOnlyAttachments
	err, resp := SendEmail(ctx, req)
	return err, resp
}

// 获取单个链接
func getSingleLink(body *string) string {
	if body == nil || strings.TrimSpace(*body) == "" {
		return ""
	}
	bodyString := *body
	startIndex := strings.Index(bodyString, "href=\"")
	if startIndex == -1 {
		return ""
	}
	endIndex := strings.Index(bodyString[startIndex+6:], "\"") + startIndex + 6
	res := bodyString[startIndex+6 : endIndex]
	aEndIndex := strings.Index(bodyString, "</a>")
	*body = bodyString[aEndIndex+1:]
	return res
}

// 获取单张图片的标签
func getSingleImg(body *string) string {
	if body == nil || strings.TrimSpace(*body) == "" {
		return ""
	}
	bodyString := *body
	startIndex := strings.Index(bodyString, "<img")
	if startIndex == -1 {
		return ""
	}
	endIndex := strings.Index(bodyString[startIndex+4:], ">") + startIndex + 4
	imgTag := bodyString[startIndex : endIndex+1]
	*body = bodyString[endIndex+1:]
	return imgTag
}

// Deprecated
// 将img标签替换，去除所有其余属性，只保留src
func handlePreImgToPureImg(body *string, from int) int {
	if body == nil || strings.TrimSpace(*body) == "" {
		return -1
	}
	preBody := *body
	bodyString := preBody[from:]
	startIndex := strings.Index(bodyString, "<img")
	if startIndex == -1 {
		return -1
	}
	endIndex := strings.Index(bodyString[startIndex+4:], ">") + startIndex + 4
	img := bodyString[startIndex : endIndex+1]
	srcStartIndex := strings.Index(img, "data-src=\"")
	srcEndIndex := strings.Index(img[srcStartIndex+10:], "\"") + srcStartIndex + 10
	res := img[srcStartIndex+10 : srcEndIndex]
	res = fmt.Sprintf("<img src=\"%s\">", res)
	*body = strings.Replace(preBody, img, res, 1)
	return from + endIndex + 1
}
